package com.macro.mall.portal.controller.ums;

import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
import com.alibaba.fastjson.JSON;
import com.macro.mall.boot.wechat.mp.WxMpConfig;
import com.macro.mall.common.api.CommonResult;
import com.macro.mall.common.api.util.StringUtils;
import com.macro.mall.portal.controller.BaseController;
import com.macro.mall.portal.dto.ums.CreateJsapiSignatureReqDto;
import com.macro.mall.portal.util.GenderUtils;
import com.macro.mall.portal.util.WebUtils;
import com.macro.mall.ums.entity.WxMemberEntity;
import com.macro.mall.ums.enums.UserGenderEnum;
import com.macro.mall.ums.enums.UserSourceTypeEnum;
import com.macro.mall.ums.service.account.WxMemberService;
import com.macro.mall.ums.service.login.WxLoginService;
import com.macro.mall.ums.service.login.bo.LoginByWxMpInput;
import com.macro.mall.ums.service.login.bo.MemberLoginResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 微信公众号授权
 *
 * @author xuyanjun
 * @date 2019-11-15
 */
@Api(tags = "WxMpAuthController", description = "微信公众号授权登录")
@Slf4j(topic = "WxMpAuthController")
@Controller
public class WxMpAuthController extends BaseController {

    private static ExecutorService executorService = Executors.newFixedThreadPool(1);

    @Value("${wx-mp.front-url}")
    private String wxMpFrontUrl;

    @Autowired
    private WxLoginService wxLoginService;

    @Autowired
    private WxMemberService wxMemberService;

    /**
     * 未授权时的首页
     *
     * @param parentId 上级id
     */
    @ApiOperation("微信授权首页")
    @GetMapping("/wxMpAuth/index")
    public String index(@RequestParam(value = "parentId", required = false) Integer parentId,
                        @RequestParam(value = "platformId", required = false) Integer platformId) {

        WxMpService wxMpService = obtainWxMpService();

        // 第三方平台只需要获取用户的openId
        String scope = WxConsts.OAuth2Scope.SNSAPI_USERINFO;

        String state = String.format("%s,%s", parentId == null ? 0 : parentId, platformId == null ? 0 : platformId);

        String url = WebUtils.getRequestDomain() + "wxMpAuth/callback";
        String authorizationUrl = wxMpService.oauth2buildAuthorizationUrl(url, scope, state);

        return "redirect:" + authorizationUrl;
    }

    /**
     * 微信回调页
     *
     * @param code  wxCode
     * @param state parentId,platformId
     */
    @GetMapping("/wxMpAuth/callback")
    public String callback(@RequestParam(value = "code") String code,
                           @RequestParam(value = "state", required = false) String state) throws WxErrorException {

        log.info("WxMpLoginCallback code:{},state:{}", code, state);

        List<String> split = StringUtils.splitTrim(state, ",");

        Long parentId = Long.valueOf(split.get(0));
        Integer platformId = Integer.valueOf(split.get(1));
        parentId = parentId == 0 ? null : parentId;
        platformId = platformId == 0 ? null : platformId;

        WxMpService wxMpService = obtainWxMpService();

        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);

        WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);

        UserGenderEnum userGenderEnum = GenderUtils.wxGenderToUserGender(String.valueOf(wxMpUser.getSex()));

        LoginByWxMpInput loginByWxMpInput = new LoginByWxMpInput();
        loginByWxMpInput.setOpenId(wxMpUser.getOpenId())
                .setUnionId(wxMpUser.getUnionId())
                .setBefId(parentId)
                .setNickname(wxMpUser.getNickname())
                .setHeadImgUrl(wxMpUser.getHeadImgUrl())
                .setCountry(wxMpUser.getCountry())
                .setProvince(wxMpUser.getProvince())
                .setCity(wxMpUser.getCity())
                .setUserGenderEnum(userGenderEnum)
                .setLoginIp(WebUtils.getRemoteIp())
                .setUserAgent(WebUtils.getUserAgent());

        loginByWxMpInput.setUserSourceTypeEnum(UserSourceTypeEnum.WX_MP);

        MemberLoginResult ssoUserLoginResult = wxLoginService.loginByWxMp(loginByWxMpInput);

        if (Boolean.TRUE.equals(ssoUserLoginResult.getNewUser()) && parentId != null && parentId > 0) {
            sendNewUserMpTemplateIdAsync(parentId);
        }

        log.info("响应结果 Response:{}", JSON.toJSONString(ssoUserLoginResult));

        return "redirect:" + wxMpFrontUrl + "?token=" + ssoUserLoginResult.getAccessToken() + "&platformId=" + (platformId == null ? "" : platformId);
    }

    private WxMpService obtainWxMpService() {
        return WxMpConfig.getWxMpServiceByBusinessAppId(UserSourceTypeEnum.WX_MP.getValue());
    }

    private void sendNewUserMpTemplateIdAsync(long userId) {
        executorService.execute(() -> {
            try {
                sendNewUseMpTemplate(userId);
            } catch (Exception e) {
                log.error(e.getMessage());
            }

        });

    }

    private void sendNewUseMpTemplate(long userId) throws WxErrorException {
        WxMemberEntity wxMemberEntity = wxMemberService.getByMemberId(userId);
        if (wxMemberEntity == null) {
            return;
        }

        List<WxMpTemplateData> wxMpTemplateDataList = new ArrayList<>();
        wxMpTemplateDataList.add(new WxMpTemplateData("first","又有新成员加入了"));
        wxMpTemplateDataList.add(new WxMpTemplateData("keyword1",wxMemberEntity.getWxNickname()));
        wxMpTemplateDataList.add(new WxMpTemplateData("keyword2", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yy-MM-dd HH:mm:ss"))));
        wxMpTemplateDataList.add(new WxMpTemplateData("remark","队伍又壮大了一步，继续加油哦"));

        WxMpTemplateMessage wxMpTemplateMessage = new WxMpTemplateMessage();
        wxMpTemplateMessage.setData(wxMpTemplateDataList);
        wxMpTemplateMessage.setToUser(wxMemberEntity.getWxOpenId());
        wxMpTemplateMessage.setTemplateId("oixPXW5oj3kt2-Mr-yBnt6eKPu82dEX6pDx-xYSSOW8");

        WxMpConfig.getWxMpServiceByBusinessAppId(UserSourceTypeEnum.WX_MP.getValue())
                .getTemplateMsgService()
                .sendTemplateMsg(wxMpTemplateMessage);
    }

    /**
     * 生成jsapi签名
     */
    @ApiOperation("获取微信jsapi签名")
    @PostMapping("createJsapiSignature")
    @ResponseBody
    public CommonResult<WxJsapiSignature> createJsapiSignature(@RequestBody CreateJsapiSignatureReqDto reqDto) throws WxErrorException {
        String url = reqDto.getUrl();

        WxMpService wxMpService = obtainWxMpService();
        WxJsapiSignature jsapiSignature = wxMpService.createJsapiSignature(url);

        return CommonResult.success(jsapiSignature);
    }
}
